import UI_Hierarchy from "../../ui/Main/UI_Hierarchy";
import BaseUIMediator from "../../LTGame/UI/BaseUIMediator";
import UI_view_item_hierachy from "../../ui/Main/UI_view_item_hierachy";
import { DebuggerManager } from "../debugger/DebuggerManager";
import { ObjData } from "../debug_inject/common/ObjData";
import { EMessageC2C } from "../../common/EMessageC2C";
import { TransPack } from "../../server/framework/common/TransPack";
import { StringEx } from "../../LTGame/Utils/StringEx";
import ArrayEx from "../../LTGame/Utils/ArrayEx";
import { NodeTypeHelper } from "../debug_inject/action/NodeTypeHelper";
import { EventCenter } from "../../LTGame/Event/EventCenter";
import { EventIDs } from "../common/EventIds";
import { ViewStatus } from "./view/ViewStatus";
import MonoHelper, { EActionType } from "../../LTGame/Utils/MonoHelper";

const UNIT_LEVEL_WIDTH = 20;
export default class UI_HierarchyMediator extends BaseUIMediator<UI_Hierarchy> {

    private static _instance: UI_HierarchyMediator;
    public static get instance(): UI_HierarchyMediator {
        if (this._instance == null) {
            this._instance = new UI_HierarchyMediator();
            this._instance._classDefine = UI_Hierarchy;
        }
        return this._instance;
    }

    private _cacheRootNode: DisplayNode;
    private _cacheClientList: DisplayNode[];

    private _selectIds: number[];
    private _lastClickTick: number;

    private _viewStatus: ViewStatus;

    private _skipTime: number;

    _OnShow() {
        super._OnShow();
        // your code

        this._cacheClientList = [];
        this._lastClickTick = 0;
        this._selectIds = [];
        this.ui.setXY(10, 10);
        this.ui.setSize(this.ui.width, this.ui.parent.height - 20);

        this._viewStatus = new ViewStatus(this.ui.m_view_status);

        this.ui.m_btn_refresh.onClick(this, this._OnClickRefresh);

        this.ui.m_list_objs.setVirtual();
        this.ui.m_list_objs.itemRenderer = Laya.Handler.create(this, this._OnItemRender, null, false);

        this._QueryObjList(true);

        EventCenter.instance.Regist(EventIDs.RefreshObjList, this, this._OnRecvRefreshEvent);
        DebuggerManager.instance.RegistClientMsg(EMessageC2C.QueryObjList_Back, this, this._OnMsgBack);

        MonoHelper.instance.AddAction(EActionType.Update, this, this._LogicUpdate);
    }

    _OnHide() {
        MonoHelper.instance.RemoveAction(EActionType.Update, this, this._LogicUpdate);

        EventCenter.instance.UnRegist(EventIDs.RefreshObjList, this, this._OnRecvRefreshEvent);
        DebuggerManager.instance.UnRegistClientMsg(EMessageC2C.QueryObjList_Back);
    }

    private _LogicUpdate(dt: number) {
        if (!this._viewStatus.isQuery) {
            this._skipTime -= dt;
            if (this._skipTime < 0) {
                this._QueryObjList(false);
            }
        }
    }

    private _OnRecvRefreshEvent() {
        if (this._viewStatus.isQuery) {
            return;
        }
        this._QueryObjList(false);
    }

    private _OnMsgBack(pack: TransPack) {
        this._viewStatus.isQuery = false;
        this._skipTime = 0.4;
        if (pack.data == null) return;
        let rootNode = new DisplayNode();
        rootNode.isFold = false;
        this._SearchNode(pack.data, rootNode, 1);
        this._cacheRootNode = rootNode;
        this._RebuildList();
    }

    private _RebuildList() {
        this._cacheClientList = [];
        this._BuildList(this._cacheRootNode, this._cacheClientList);
        this.ui.m_list_objs.numItems = this._cacheClientList.length;
        this.ui.m_list_objs.refreshVirtualList();
    }

    private _BuildList(workNode: DisplayNode, cacheList: DisplayNode[]) {
        cacheList.push(workNode);
        if (!workNode.isFold) {
            for (let i = 0; i < workNode.childs.length; ++i) {
                let getNode = workNode.childs[i];
                this._BuildList(getNode, cacheList);
            }
        }
    }

    private _SearchNode(obj: ObjData, displayNode: DisplayNode, foldLevel: number) {
        displayNode.data = obj;
        displayNode.foldLevel = foldLevel++;

        for (let i = 0; i < this._cacheClientList.length; ++i) {
            let cacheClient = this._cacheClientList[i];
            if (cacheClient.id == displayNode.id) {
                displayNode.isFold = cacheClient.isFold;
            }
        }

        for (let i = 0; i < obj.c.length; ++i) {
            let getObj = obj.c[i];
            let newNode = new DisplayNode();
            this._SearchNode(getObj, newNode, foldLevel);
            displayNode.childs.push(newNode);
        }
    }

    private _OnItemRender(index: number, itemUI: UI_view_item_hierachy) {
        let nodeData = this._cacheClientList[index];
        if (nodeData == null) return;
        // name
        itemUI.m_text_value.text = nodeData.CalcName();
        itemUI.m_text_value.x = 32 + nodeData.foldLevel * UNIT_LEVEL_WIDTH;
        itemUI.m_state_active.selectedIndex = nodeData.active ? 1 : 0;
        // fold_img
        if (nodeData.childs.length > 0) {
            itemUI.m_img_fold.x = 15 + nodeData.foldLevel * UNIT_LEVEL_WIDTH;
            if (nodeData.isFold) {
                itemUI.m_img_fold.m_img.rotation = -90;
            } else {
                itemUI.m_img_fold.m_img.rotation = 0;
            }
            itemUI.m_img_fold.visible = true;
        } else {
            itemUI.m_img_fold.visible = false;
        }

        // select_bg
        itemUI.m_img_selected.visible = ArrayEx.Contains(this._selectIds, nodeData.id);

        itemUI.m_img_bg.onClick(this, this._OnClickItem, [index]);
        itemUI.m_img_fold.onClick(this, this._OnClickToggleIcon, [index]);
    }

    private _OnClickItem(index: number) {
        let clickData = this._cacheClientList[index];
        if (ArrayEx.Contains(this._selectIds, clickData.id)) {
            let passTick = Date.now() - this._lastClickTick;
            if (passTick < 0.2 * 1000) {
                clickData.isFold = !clickData.isFold;
                this._RebuildList();
                this._lastClickTick = 0;
            } else {
                this._lastClickTick = Date.now();
            }
            return;
        }
        this._lastClickTick = Date.now();
        this._selectIds = [clickData.id];
        EventCenter.instance.Send(EventIDs.SelectObj, [this._selectIds]);
        this.ui.m_list_objs.refreshVirtualList();
    }

    private _OnClickToggleIcon(index: number) {
        let clickData = this._cacheClientList[index];
        clickData.isFold = !clickData.isFold;
        this._RebuildList();
    }

    private _OnClickRefresh() {
        if (this._viewStatus.isQuery) {
            return;
        }
        this._QueryObjList(true);
    }

    private _QueryObjList(isForce: boolean) {
        DebuggerManager.instance.QueryObjList(isForce);
        this._viewStatus.isQuery = true;
    }

}

class DisplayNode {

    data: ObjData;

    isFold: boolean = true;

    foldLevel: number = 0;

    childs: DisplayNode[] = [];

    public get id(): number {
        return this.data.i;
    }

    public get active(): boolean {
        return this.data.a;
    }

    public CalcName(): string {
        let name = this.data.n;
        if (StringEx.IsNullOrEmpty(name)) {
            name = `<${NodeTypeHelper.GetTypeName(this.data.t)}>`;
        }
        return name;
    }
}